package com.swind.fast.modules.app.halali.partner.service.impl;

import com.swind.fast.common.util.oConvertUtils;

import com.swind.fast.modules.app.halali.partner.entity.Restaurant;
// import com.swind.fast.modules.app.halali.partner.entity.RestaurantBill;
import com.swind.fast.modules.app.halali.partner.mapper.RestaurantMapper;
import com.swind.fast.modules.app.halali.partner.service.IRestaurantService;
// import com.swind.fast.modules.app.halali.partner.model.SpaceAnnouncementModel;

import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.ApplicationContext;

import org.apache.ibatis.annotations.Param;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import cn.hutool.core.date.DateBetween;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;

import javax.annotation.Resource;

import java.util.stream.Collectors;

import lombok.extern.slf4j.Slf4j;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.ArrayList;

import com.swind.fast.modules.app.halali.partner.entity.RestaurantOperation;
import com.swind.fast.modules.app.halali.partner.service.IRestaurantOperationService;
import com.swind.fast.modules.app.halali.partner.entity.Order;
import com.swind.fast.modules.app.halali.partner.service.IOrderService;
import com.swind.fast.modules.app.halali.partner.vo.response.RestaurantInfoVo;
import com.swind.fast.modules.app.halali.partner.vo.response.PartnerHomeVo;
import com.swind.fast.modules.app.halali.partner.vo.request.RestaurantVo;

import org.springframework.beans.BeanUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.stream.Collectors;

import org.apache.shiro.SecurityUtils;
import com.swind.fast.common.system.vo.HalaliLoginUser;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.springframework.beans.factory.annotation.Value;
import com.swind.fast.modules.app.halali.partner.vo.response.RestaurantInfoVo;
import com.swind.fast.common.util.DateUtils;

import com.swind.fast.modules.app.halali.partner.entity.BankAccount;
import com.swind.fast.modules.app.halali.partner.vo.request.BankAccountVo;
import com.swind.fast.modules.app.halali.partner.service.IBankAccountService;

/**
 * @Description: 项目
 * @Author: swind
 * @Date:   2021-11-20
 * @Version: V1.0
 */
@Slf4j
@Service
public class RestaurantServiceImpl extends ServiceImpl<RestaurantMapper, Restaurant> implements IRestaurantService {
    @Value(value = "${swind.path.preview}")
    private String previewPath;

    @Autowired
    private IOrderService orderService;

    @Autowired
    private IRestaurantOperationService restaurantOperationService;

    @Autowired
    private IBankAccountService bankAccountService;

    public RestaurantInfoVo getDetailInfo(String id) {
        RestaurantInfoVo result = new RestaurantInfoVo();
        this.getBasicInfo(id, result);
        this.getOperationInfo(id, result);
        this.getMonthlyRevenue(result);
        this.renderPic(result);
        this.getBankAccountInfo(id, result);
        return result;
    }

    private void getOperationInfo(String id, RestaurantInfoVo result) {
        RestaurantOperation operation = this.baseMapper.queryOperationByRestaurantId(id);
        if (oConvertUtils.isNotEmpty(operation)) {
            BeanUtils.copyProperties(operation, result);
            result.setIsOpen(this.checkIfOpen(operation));
        }
    }

    private void getBasicInfo(String id, RestaurantInfoVo result) {
        Restaurant restaurant = this.getById(id);
        BeanUtils.copyProperties(restaurant, result);
    }

    public RestaurantOperation getOperationById(String id) {
        return this.baseMapper.queryOperationByRestaurantId(id);
    }

    private void getBankAccountInfo(String id, RestaurantInfoVo result) {
        BankAccount item = this.bankAccountService.getByRestaurantId(id);
        if (oConvertUtils.isNotEmpty(item)) {
            result.setBankAccount(item);
        }
    }

    public PartnerHomeVo getHomeResult(String id) {
        PartnerHomeVo result = new PartnerHomeVo();

        Restaurant restaurant = this.getById(id);
        result.setTitle(restaurant.getTitle());

        RestaurantOperation operation = this.baseMapper.queryOperationByRestaurantId(id);
        result.setCloseAt(operation.getCloseAt());
        result.setIsOpen(this.checkIfOpen(operation));

        this.getTodayData(result, id);
        result.setUpdateAt(DateUtils.now());
        return result;
    }

    private void getTodayData(PartnerHomeVo result, String id) {
        // LocalDateTime startOfToday = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
        LocalDateTime startOfToday = DateUtils.startOfToday();
        List<Order> orders = baseMapper.queryTodayOrderByRestaurantId(id, startOfToday);

        if (orders.size() < 1) return;

        Double totalPrice = orders.stream().mapToDouble(Order::getTotalPrice).sum();
        result.setRevenue(totalPrice);
        result.setTotalOrders(orders.size());

        List<Order> cancel = orders.stream().filter(e -> (e.getState() == -1)).collect(Collectors.toList());
        result.setCancelOrders(cancel.size());
    }

    private Boolean checkIfOpen(RestaurantOperation operation) {
        Boolean isOpen = false;

        if (!operation.getIsOpen()) {
            return isOpen;
        }

        String openAt = operation.getOpenAt();
        String closeAt = operation.getCloseAt();
        // 创建DateTimeFormatter对象
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm");

        // 解析字符串为LocalTime对象
        LocalTime startTime = LocalTime.parse(openAt, formatter);
        LocalTime endTime = LocalTime.parse(closeAt, formatter);
        LocalTime currentTime = LocalTime.now();

        if (currentTime.isAfter(startTime) && currentTime.isBefore(endTime)) {
            isOpen = true;
        }

        return isOpen;
    }

    public RestaurantInfoVo updateInfo(RestaurantVo info) {
        RestaurantInfoVo result = new RestaurantInfoVo();

        HalaliLoginUser sysUser = (HalaliLoginUser) SecurityUtils.getSubject().getPrincipal();
        String id = sysUser.getRestaurantId();
        Restaurant restaurant = this.getById(id);
        if (!oConvertUtils.isEmpty(info.getPic())) {
            restaurant.setPic(info.getPic());
        }
        if (!oConvertUtils.isEmpty(info.getLogoUrl())) {
            restaurant.setLogoUrl(info.getLogoUrl());
        }
        if (!oConvertUtils.isEmpty(info.getPhone())) {
            restaurant.setPhone(info.getPhone());
        }
        if (!oConvertUtils.isEmpty(info.getTitle())) {
            restaurant.setTitle(info.getTitle());
        }
        if (!oConvertUtils.isEmpty(info.getDescription())) {
            restaurant.setDescription(info.getDescription());
        }
        this.updateById(restaurant);

        Boolean isModify = false;
        LambdaUpdateWrapper<RestaurantOperation> updateWrapper = new LambdaUpdateWrapper<RestaurantOperation>();
        updateWrapper.eq(RestaurantOperation::getRestaurantId, id);
        if (!oConvertUtils.isEmpty(info.getIsOpen())) {
            updateWrapper.set(RestaurantOperation::getIsOpen, info.getIsOpen());
            isModify = true;
        }
        if (!oConvertUtils.isEmpty(info.getOpenAt())) {
            updateWrapper.set(RestaurantOperation::getOpenAt, info.getOpenAt());
            isModify = true;
        }
        if (!oConvertUtils.isEmpty(info.getCloseAt())) {
            updateWrapper.set(RestaurantOperation::getCloseAt, info.getCloseAt());
            isModify = true;
        }
        if (!oConvertUtils.isEmpty(info.getOpenWeekday())) {
            updateWrapper.set(RestaurantOperation::getOpenWeekday, info.getOpenWeekday());
            isModify = true;
        }
        if (!oConvertUtils.isEmpty(info.getMinOrder())) {
            updateWrapper.set(RestaurantOperation::getMinOrder, info.getMinOrder());
            isModify = true;
        }
        if (!oConvertUtils.isEmpty(info.getProvisionTime())) {
            updateWrapper.set(RestaurantOperation::getProvisionTime, info.getProvisionTime());
            isModify = true;
        }

        if (isModify) {
            this.restaurantOperationService.update(updateWrapper);
        }

        RestaurantOperation operation = this.baseMapper.queryOperationByRestaurantId(id);

        BeanUtils.copyProperties(restaurant, result);
        BeanUtils.copyProperties(operation, result);

        return result;
    }

    public void renderPic(RestaurantInfoVo info) {
        if (oConvertUtils.isNotEmpty(info.getPic()) && !info.getPic().startsWith("http")) {
            String picPath = this.previewPath + "/" + info.getPic();
            info.setPic(picPath);
        }

        if (oConvertUtils.isNotEmpty(info.getLogoUrl()) && !info.getLogoUrl().startsWith("http")) {
            String logoPath = this.previewPath + "/" + info.getLogoUrl();
            info.setLogoUrl(logoPath);
        }

        if (oConvertUtils.isNotEmpty(info.getHalaliCertImgUrl()) && !info.getHalaliCertImgUrl().startsWith("http")) {
            String halaliCertImgUrl = this.previewPath + "/" + info.getHalaliCertImgUrl();
            info.setHalaliCertImgUrl(halaliCertImgUrl);
        }

        if (oConvertUtils.isNotEmpty(info.getLicenseImgUrl()) && !info.getLicenseImgUrl().startsWith("http")) {
            String licenseImgUrl = this.previewPath + "/" + info.getLicenseImgUrl();
            info.setLicenseImgUrl(licenseImgUrl);
        }
    }

    private void getMonthlyRevenue(RestaurantInfoVo info) {
        Double monthly = this.orderService.getMonthlyRevenue();
        info.setMonthlyRevenue(monthly);
    }

    public BankAccount updateBankInfo(BankAccountVo info) {
        BankAccount item = this.bankAccountService.saveMain(info);
        return item;
    }

}
